package com.soyotec.algorithm.util;

import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;

import java.io.IOException;
import java.lang.reflect.Field;

public class SystemUtils {
    /**
     * 杀死指定进程数，即包括process进程的所有子进程
     *
     * @param process
     */
    public static void killProcessTree(Process process) {
        if (process != null && process.isAlive()) {
            String pid=  getProcessId(process);
            killProcessByPid(pid);

        }
//        try {
//
//
//            String osName = System.getProperty("os.name");
//            if(osName.startsWith("Linux")){
//                command = "kill -9 " + pid;
//
//            }else{
//                System.out.println("-------------------close process tree:"+process.isAlive());
//                if (process != null && process.isAlive()) {
//                    try {
//                        System.out.println("-------------------close process tree1:" + process.isAlive());
//                        Field f = process.getClass().getDeclaredField("handle");
//
//                        f.setAccessible(true);
//
//                        System.out.println("----------------------------------1");
//                        long handl = f.getLong(process);
//                        System.out.println("----------------------------------1。1");
//                        Kernel32 kernel = Kernel32.INSTANCE;
//                        System.out.println("----------------------------------1。2");
//                        WinNT.HANDLE handle = new WinNT.HANDLE();
//
//                        System.out.println("----------------------------------2");
//                        handle.setPointer(Pointer.createConstant(handl));
//
//                        int ret = kernel.GetProcessId(handle);
//                        System.out.println("----------------------------------3");
//                        Long PID = Long.valueOf(ret);
//
//                        String cmd = "cmd /c taskkill /PID " + PID + " /F /T ";
//                        System.out.println("-------------------close process tree cmd：" + cmd);
//                        Runtime rt = Runtime.getRuntime();
//                        Process killPrcess = rt.exec(cmd);
//                        killPrcess.waitFor();
//                        killPrcess.destroyForcibly();
//                    }catch(Exception e){
//                        e.printStackTrace();
//                    }
//                }
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }
    public static boolean killProcessByPid(String pid){
        if(pid==null){
            pid="";
        }
        if (pid.trim().equals("") || "-1".equals(pid)) {
            throw new RuntimeException("Pid ==" + pid);
        }
        Process process = null;
//        BufferedReader reader =null;
        String command = "";
        boolean result = false;
        if (Platform.isWindows()) {
            command = "cmd.exe /c taskkill /PID " + pid + " /F /T ";
        } else if (Platform.isLinux() || Platform.isAIX()) {
            command = "kill -9 " + pid;
        }
        try{
            //杀掉进程
//            System.out.println("command:"+command);
            process = Runtime.getRuntime().exec(command);
            process.waitFor();
//            reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
//            String line = null;
//            while((line = reader.readLine())!=null){
//                log.info("kill PID return info -----> "+line);
//            }
            result = true;
        }catch(Exception e){
            e.printStackTrace();
//            log.info("杀进程出错：", e);
            result = false;
        }finally{
            if(process!=null){
                process.destroy();
            }
//            if(reader!=null){
//                try {
//                    reader.close();
//                } catch (IOException e) {
//
//                }
//            }
        }
        return result;
    }
    public static String getProcessId(Process process) {
        long pid = -1;
        Field field = null;

        String osName = System.getProperty("os.name");
//        System.out.println("----------------------------------1:"+osName);
//        System.out.println("---------------------------------Platform.isWindows():"+Platform.isWindows());
        if (Platform.isWindows()||osName.startsWith("Win")) {
//            System.out.println("----------------------------------1。2:"+osName);
            try {
//                System.out.println("----------------------------------2");
                field = process.getClass().getDeclaredField("handle");
                field.setAccessible(true);
                WinNT.HANDLE handle = new WinNT.HANDLE();
//                System.out.println("----------------------------------3");
                handle.setPointer(Pointer.createConstant((Long) field.get(process)));
//                System.out.println("----------------------------------4");
                pid = Kernel32.INSTANCE.GetProcessId(handle);
//                System.out.println("----------------------------------5");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } else if (Platform.isLinux() || Platform.isAIX()) {
            try {
                Class<?> clazz = Class.forName("java.lang.UNIXProcess");
                field = clazz.getDeclaredField("pid");
                field.setAccessible(true);
                pid = (Integer) field.get(process);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return String.valueOf(pid);
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        String osName = System.getProperty("os.name");
        System.out.println(osName);
        System.out.println(osName.startsWith("Win"));
        System.out.println(Platform.isWindows());
        Process p=Runtime.getRuntime().exec("notepad");

        new Thread(()->{

            System.out.println("open notepad end");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SystemUtils.killProcessTree(p);
            System.out.println("kill notepad end");
            System.out.println(" process status:"+p.isAlive());
        }).start();
        p.waitFor();
    }
}
